//****************************************************
// Porman Project 
// Filename: CRenderViewport.cpp
// Date: 2011/01/15
// Author: KengYu Lin
// Modify:
//****************************************************
#include "CRenderCamera.h"
#include "CRenderSystem.h"
#include "CRenderTarget.h"
#include "CRenderViewport.h"

namespace Porman
{

namespace RS
{

CRenderViewport::CRenderViewport( const std::string& sName, unsigned int uiHash ) :
CRenderBase(sName,uiHash),
m_hViewportData()
{
}

CRenderViewport::~CRenderViewport( void )
{
}

void CRenderViewport::initial( CRenderTarget* pRT, CRenderCamera* pCamera, int iZOrder, float fOffsetX, float fOffsetY, float fWidth, float fHeight )
{
    m_pRT = pRT;
    m_iZOrder = iZOrder;

    m_hViewportData.getData().m_pCamera = pCamera;
    m_hViewportData.getData().m_fOffsetX = fOffsetX;
    m_hViewportData.getData().m_fOffsetY = fOffsetY;
    m_hViewportData.getData().m_fWidth = fWidth;
    m_hViewportData.getData().m_fHeight = fHeight;
}

void CRenderViewport::setBackgroundColor( float fColor[4] )
{
    memcpy( m_hViewportData.getData().m_fColor, fColor, sizeof(float)*4 );
}

void CRenderViewport::getBackgroundColor( float fColor[4] )
{
    memcpy( fColor, m_hViewportData.getData().m_fColor, sizeof(float)*4 );
}

void CRenderViewport::setDepth( float fDepth )
{
    m_hViewportData.getData().m_fDepth = fDepth;
}

float CRenderViewport::getDepth( void )
{
    return m_hViewportData.getData().m_fDepth;
}

void CRenderViewport::setStencil( int iStencil )
{
    m_hViewportData.getData().m_iStencil = iStencil;
}

int CRenderViewport::getStencil( void )
{
    return m_hViewportData.getData().m_iStencil;
}

void CRenderViewport::setActualMertics( int iOffsetX, int iOffsetY, int iWidth, int iHeight )
{
    int iW, iH;
    m_pRT->getMetrics( iW, iH );

    m_hViewportData.getData().m_fOffsetX = static_cast<float>( iOffsetX / iW );
    m_hViewportData.getData().m_fOffsetY = static_cast<float>( iOffsetY / iH );
    m_hViewportData.getData().m_fWidth = static_cast<float>( iWidth / iW );
    m_hViewportData.getData().m_fHeight = static_cast<float>( iHeight / iH );
}

void CRenderViewport::getActualMertics( int& iOffsetX, int& iOffsetY, int& iWidth, int& iHeight )
{
    int iW, iH;
    m_pRT->getMetrics( iW, iH );

    iOffsetX = static_cast<int>( m_hViewportData.getData().m_fOffsetX * iW );
    iOffsetY = static_cast<int>( m_hViewportData.getData().m_fOffsetY * iH );
    iWidth = static_cast<int>( m_hViewportData.getData().m_fWidth * iW );
    iHeight = static_cast<int>( m_hViewportData.getData().m_fHeight * iH );
}

void CRenderViewport::setActualOffsetX( int iOffsetX )
{
    int iW = m_pRT->getWidth();
    m_hViewportData.getData().m_fOffsetX = static_cast<float>( iOffsetX / iW );
}

int CRenderViewport::getActualOffsetX( void )
{
    int iW = m_pRT->getWidth();
    return static_cast<int>( m_hViewportData.getData().m_fOffsetX * iW );
}

void CRenderViewport::setAcutalOffsetY( int iOffsetY )
{
    int iH = m_pRT->getHeight();
    m_hViewportData.getData().m_fOffsetY = static_cast<float>( iOffsetY / iH );
}

int CRenderViewport::getActualOffsetY( void )
{
    int iH = m_pRT->getHeight();
    return static_cast<int>( m_hViewportData.getData().m_fOffsetY * iH );
}

void CRenderViewport::setActualWidth( int iWidth )
{
    int iW = m_pRT->getWidth();
    m_hViewportData.getData().m_fWidth = static_cast<float>( iWidth / iW );
}

int CRenderViewport::getActualWidth( void )
{
    int iW = m_pRT->getWidth();
    return static_cast<int>( m_hViewportData.getData().m_fWidth * iW );
}

void CRenderViewport::setActualHeight( int iHeight )
{
    int iH = m_pRT->getHeight();
    m_hViewportData.getData().m_fHeight = static_cast<float>( iHeight / iH );
}

int CRenderViewport::getActualHeight( void )
{
    int iH = m_pRT->getHeight();
    return static_cast<int>( m_hViewportData.getData().m_fHeight * iH );
}

void CRenderViewport::setMertics( float fOffsetX, float fOffsetY, float fWidth, float fHeight )
{
    m_hViewportData.getData().m_fOffsetX = fOffsetX;
    m_hViewportData.getData().m_fOffsetY = fOffsetY;
    m_hViewportData.getData().m_fWidth = fWidth;
    m_hViewportData.getData().m_fHeight = fHeight;
}

void CRenderViewport::getMertics( float& fOffsetX, float& fOffsetY, float& fWidth, float& fHeight )
{
    fOffsetX = m_hViewportData.getData().m_fOffsetX;
    fOffsetY = m_hViewportData.getData().m_fOffsetY;
    fWidth = m_hViewportData.getData().m_fWidth;
    fHeight = m_hViewportData.getData().m_fHeight;
}

void CRenderViewport::setOffsetX( float fOffsetX )
{
    m_hViewportData.getData().m_fOffsetX = fOffsetX;
}

float CRenderViewport::getOffsetX( void )
{
    return m_hViewportData.getData().m_fOffsetX;
}

void CRenderViewport::setAcutalOffsetY( float fOffsetY )
{
    m_hViewportData.getData().m_fOffsetY = fOffsetY;
}

float CRenderViewport::getOffsetY( void )
{
    return m_hViewportData.getData().m_fOffsetY;
}

void CRenderViewport::setWidth( float fWidth )
{
    m_hViewportData.getData().m_fWidth = fWidth;
}

float CRenderViewport::getWidth( void )
{
    return m_hViewportData.getData().m_fWidth;
}

void CRenderViewport::setHeight( float fHeight )
{
    m_hViewportData.getData().m_fHeight = fHeight;
}

float CRenderViewport::getHeight( void )
{
    return m_hViewportData.getData().m_fHeight;
}

void CRenderViewport::onSwap( void ) 
{ 
    m_hViewportData.getRenderData().m_pCamera = m_hViewportData.getData().m_pCamera;
    m_hViewportData.swap();
}

void CRenderViewport::onRender( void ) 
{
    CRenderCamera* pCamera = m_hViewportData.getRenderData().m_pCamera;
    if( pCamera )
    {
        //-----------------------------------------------------
        // According properties of RenderUnity to class...
        //-----------------------------------------------------
        CRenderUnityList& Unities = pCamera->getRenderUnityList();
        for( size_t i=0; i<Unities.size(); i++ )
        {
            CRenderUnity* pUnity = Unities[i];
        }

        //------------------------------
        // Ready for rendering...
        //------------------------------
        int iX = static_cast<int>( m_hViewportData.getRenderData().m_fOffsetX * m_pRT->getWidth() );
        int iY = static_cast<int>( m_hViewportData.getRenderData().m_fOffsetY * m_pRT->getHeight() );
        int iWidth = static_cast<int>( m_hViewportData.getRenderData().m_fWidth * m_pRT->getWidth() );
        int iHeight = static_cast<int>( m_hViewportData.getRenderData().m_fHeight * m_pRT->getHeight() );

        GL::CScissorStateObject ScissorStateObj;
        ScissorStateObj.m_bEnable = true;
        ScissorStateObj.m_iX = iX;
        ScissorStateObj.m_iY = iY;
        ScissorStateObj.m_iWidth = iWidth;
        ScissorStateObj.m_iHeight = iHeight;

        CRenderSystem::getSingleton().getDevice()->bindScissorStateObject( ScissorStateObj );
        CRenderSystem::getSingleton().getDevice()->setViewport( iX, iY, iWidth, iHeight, 0.0f, 1.0f );
        CRenderSystem::getSingleton().getDevice()->setColorBuffer( m_hViewportData.getRenderData().m_fColor );
        CRenderSystem::getSingleton().getDevice()->clearBuffer(true, true, true);
    }
}

}//End namespace RS

}//End namespace Porman